#include "map.hpp"
#include "mapgen.hpp"
#include <fstream>
#include <allegro.h>
#include <iostream>

cMap::cMap(cItemResources * itInfo)//konstruktor klasy cMap
{
    size = new sPoint(0, 0);
    shift = new sPoint(0, 0);
    tex = load_bmp("GFX\\texturpack.bmp", default_palette);
    tex_green = load_bmp("GFX\\texturepack_green.bmp", default_palette);
    countoftransitions=0;

    loadTile();

    itemInfo = itInfo;
}


cMap::~cMap()//destruktor cMap
{
    destroy_bitmap(tex);
    destroy_bitmap(tex_green);

    for (int i = 0; i < size->x; i++)
    {
        delete[] map[i];
        delete[] map_green[i];
    }

    delete[] map;
    delete[] map_green;
    delete size;
}

void cMap::generate()
{
    int t = clock();
    cMapGen mg(64, 64, 45, MAP_TYPE_GRASSLAND);

    int firstL[] = {4, 5, 6, 7, 8};
    int firstD[] = {5, 6, 7, 8};
    std::vector <int> live(firstL, firstL + sizeof(firstL) / sizeof(int));
    std::vector <int> dead(firstD, firstD + sizeof(firstD) / sizeof(int));
    mg.setParams(live, dead, 4);
    mg.generate();
    mg.draw();
    mg.linkHoles();
    mg.draw();
    mg.texture();
    //mg.draw();

    map = new int*[mg.w];
    map_green = new int*[mg.w];
    for (int i = 0; i < mg.w; i++)
    {
        map[i] = new int[mg.h];
        map_green[i] = new int[mg.h];
        for (int j = 0; j < mg.h; j++)
        {
            map[i][j] = mg.M[i][j];
            map_green[i][j] = mg.M_G[i][j];
        }
    }

    size->x = mg.w;
    size->y = mg.h;

    fogOn = false;
    std::cout << "Generowanie mapy trwalo " << clock() - t << "ms\n";
}

void cMap::load(const char * name)//funkcja ladujaca mape z pliku . Argument: podanie sciezki DOKLADNEJ do pliku .
{
    std::fstream file;//plik z mapa
    file.open(name, std::ios::in);//otworzenie pliku

    ///WCZYTYWANIE ROZMIARU MAPY
    file >> size->x; //wczytanie szerokosci
    file >> size->y;//wczytanie wysokosc
    int w = size->x,
        h = size->y;

    ///WCZYTYWANIE MAPY PODLOZA
    map = new int*[w];//tworzenie tablicy jednowymiarowejp

    for (int i = 0; i < size->x; i++)
        map[i] = new int[h]; //tworzenie dwuwymiarowej tablicy map

    for (int y = 0; y < size->y; y++)
        for (int x = 0; x < size->x; x++)
            file >> map[x][y];//przyporzadkowanie ID dla kazdego kafelka mapy

    ///WCZYTYWANIE MAPY WODY I ZIELENII
    map_green = new int*[w];//tworzenie tablicy jednowymiarowejp

    for (int i = 0; i < size->x; i++)
        map_green[i] = new int[h]; //tworzenie dwuwymiarowej tablicy map

    for (int y = 0; y < size->y; y++)
        for (int x = 0; x < size->x; x++)
            file >> map_green[x][y];//przyporzadkowanie ID dla kazdego kafelka mapy_green

    ///WCZYTWANIE FOG OF WAR
    file >> fogOn;


    ///WCZYTYWANIE PRZEJSC:
    file >> countoftransitions;
    transition = new std::string [countoftransitions * countoftransitions];

        for (int i=0 ; i < countoftransitions * countoftransitions ; i++)
        {
            file >> transition[i];
        }


    file.close();

    ///TWORZENIE MAPY MGŁY
    if (fogOn)
    {
        fogOfWar = new bool*[(int)size->x];
        for (int i = 0; i < size->x; i++)
            fogOfWar[i] = new bool[(int)size->y];

        for (int i = 0; i < size->x; i++)
            for (int j = 0; j < size->y; j++)
                fogOfWar[i][j] = false;
    }

}

void cMap::draw(BITMAP * bufor, sPoint * show)
{
    shift->x = shift->y = 0;

    if (size->x * TILE_SIZE < bufor->w) shift->x = (bufor->w - size->x * TILE_SIZE)/2;
    if (size->y * TILE_SIZE < bufor->h) shift->y = (bufor->h - size->y * TILE_SIZE)/2;

    //rysowanie mapy
    for (int j = 0; j < bufor->h / TILE_SIZE + 2; j++)
    {
        for (int i = 0; i < bufor->w / TILE_SIZE + 2; i++)
        {
            int x = i+show->x/TILE_SIZE;
            int y = j+show->y/TILE_SIZE;
            if (!isOnMap(sPoint(x, y) * TILE_SIZE)) continue;
            if (fogOn) if (!fogOfWar[x][y]) continue;
            masked_blit(tex, bufor, map[x][y] * TILE_SIZE, 0, i * TILE_SIZE - ((int)show->x % TILE_SIZE) + shift->x, j * TILE_SIZE - ((int)show->y % TILE_SIZE) + shift->y, TILE_SIZE, TILE_SIZE);
        }
    }
    //zielen i woda
    for (int j = 0; j < bufor->h / TILE_SIZE + 2; j++)
    {
        for (int i = 0; i < bufor->w / TILE_SIZE + 2; i++)
        {
            int x = i+show->x/TILE_SIZE;
            int y = j+show->y/TILE_SIZE;
            if (!isOnMap(sPoint(x, y) * TILE_SIZE)) continue;
            if (fogOn)if (!fogOfWar[x][y]) continue;
            masked_blit(tex_green, bufor, map_green[x][y] * TILE_SIZE, 0, i * TILE_SIZE - ((int)show->x % TILE_SIZE) + shift->x, j * TILE_SIZE - ((int)show->y % TILE_SIZE) + shift->y, TILE_SIZE, TILE_SIZE);
        }
    }

    //rysowanie na mapie itemków
    for (int i = 0; i < items.size(); i++)
    {
        if (fogOn) if (!fogOfWar[items[i].x/TILE_SIZE][items[i].y/TILE_SIZE]) continue;

        if (items[i].x + ITEM_SIZE/2 >= show->x && items[i].x - ITEM_SIZE / 2 < show->x + size->x * TILE_SIZE)
        {
            if (items[i].y + ITEM_SIZE/2 >= show->y && items[i].y - ITEM_SIZE / 2 < show->y + size->y * TILE_SIZE)
            {
                masked_blit(itemInfo->img, bufor, items[i].id * ITEM_SIZE, 0, items[i].x - ITEM_SIZE/2 - show->x + shift->x, items[i].y - ITEM_SIZE/2 - show->y + shift->y, ITEM_SIZE, ITEM_SIZE);
            }
        }
    }


}

bool cMap::isOnMap(sPoint p)
{
    return p.x >= 0 && p.y >= 0 && p.x < size->x * TILE_SIZE && p.y < size->y * TILE_SIZE;
}

void cMap::loadTile()
{
    std::fstream file;
    file.open("Data\\tile.dat", std::ios::in);

    if (!file) return;

    cTileInfo t;

    while (!file.eof())
    {
        file >> t.wall;

        tile.push_back(t);
    }

    file.close();
}

void cMap::addItem(int x, int y, int id, int count)
{
    if (!isOnMap(sPoint(x, y))) return;

    items.push_back(cItemOnMap(x, y, id, count));
}


 void cMap::delete_current_map()
 {
      for (int i = 0; i < size->x; i++)
    {
        delete[] map[i];
        delete[] map_green[i];
    }

    delete[] map;
    delete[] map_green;
    delete[] transition;

 }













